#include "map.h"
#include "gauss.h"

Map::Map(void):
    id(0), name(cUNNAMED), filePath(""), topLeft(0, 0), topRight(0, 0), bottomRight(0, 0), bottomLeft(0, 0)
{}

Map::Map(const QString& aName, const unsigned long& aID):
    id(aID), name(aName), filePath(""), topLeft(0, 0), topRight(0, 0), bottomRight(0, 0), bottomLeft(0, 0)
{}

Map::~Map()
{
    name.clear();
    filePath.clear();
}

void Map::ClearMap(void)
{
    name = cUNNAMED;
    filePath.clear();
}

bool Map::SetName(const QString& aName)
{
    if(!aName.isEmpty())
    {
        name = aName;
        return true;
    }
    else
        return false;
}

QString Map::GetName(void) const
{
    return name;
}

void Map::SetID(const unsigned long& aID)
{
    id = aID;
}

unsigned long Map::GetID(void) const
{
    return id;
}

bool Map::SetFilePath(const QString& aFileName)
{
    if(!aFileName.isEmpty())
    {
        filePath = aFileName;
        return true;
    }
    else
        return false;
}

QString Map::GetFilePath(void) const
{
    return filePath;
}

void Map::SetCalibration(const GeoCoordinates topLeftPoint,
                         const GeoCoordinates topRightPoint,
                         const GeoCoordinates bottomRightPoint,
                         const GeoCoordinates bottomLeftPoint)
{
    pix.load(filePath);
    topLeft.SetLatitude(topLeftPoint.GetLatitude());
    topLeft.SetLongitude(topLeftPoint.GetLongitude());
    topRight.SetLatitude(topRightPoint.GetLatitude());
    topRight.SetLongitude(topRightPoint.GetLongitude());
    bottomRight.SetLatitude(bottomRightPoint.GetLatitude());
    bottomRight.SetLongitude(bottomRightPoint.GetLongitude());
    bottomLeft.SetLatitude(bottomLeftPoint.GetLatitude());
    bottomLeft.SetLongitude(bottomLeftPoint.GetLongitude());
    double x1,y1,x2,y2,x3,y3,x4,y4,X1,Y1,X2,Y2,X3,Y3,X4,Y4;
    /*
    x1=0;
    y1=0;
    x2=499;
    y2=0;
    x3=499;
    y3=499;
    x4=0;
    y4=499;
    */
    x1=0;
    y1=0;
    x2=pix.width()-1;
    y2=0;
    x3=pix.width()-1;
    y3=pix.height()-1;
    x4=0;
    y4=pix.height()-1;

    X1=topLeftPoint.GetLongitude();
    Y1=topLeftPoint.GetLatitude();
    X2=topRightPoint.GetLongitude();
    Y2=topRightPoint.GetLatitude();
    X3=bottomRightPoint.GetLongitude();
    Y3=bottomRightPoint.GetLatitude();
    X4=bottomLeftPoint.GetLongitude();
    Y4=bottomLeftPoint.GetLatitude();
    double a[]={
                    x1, y1, 1, 0, 0, 0, -x1*X1, -y1*X1,
                    0, 0, 0, x1, y1, 1, -x1*Y1, -y1*Y1,
                    x2, y2, 1, 0, 0, 0, -x2*X2, -y2*X2,
                    0, 0, 0, x2, y2, 1, -x2*Y2, -y2*Y2,
                    x3, y3, 1, 0, 0, 0, -x3*X3, -y3*X3,
                    0, 0, 0, x3, y3, 1, -x3*Y3, -y3*Y3,
                    x4, y4, 1, 0, 0, 0, -x4*X4, -y4*X4,
                    0, 0, 0, x4, y4, 1, -x4*Y4, -y4*Y4
               };
    double b[]={X1,Y1,X2,Y2,X3,Y3,X4,Y4};
    gauss(8,a,b);
    for (int i=0;i<8;i++)
        xXkoef[i]=b[i];
    /*
    X1=0;
    Y1=0;
    X2=499;
    Y2=0;
    X3=499;
    Y3=499;
    X4=0;
    Y4=499;
    */
    X1=0;
    Y1=0;
    X2=pix.width()-1;
    Y2=0;
    X3=pix.width()-1;
    Y3=pix.height()-1;
    X4=0;
    Y4=pix.height()-1;

    x1=topLeftPoint.GetLongitude();
    y1=topLeftPoint.GetLatitude();
    x2=topRightPoint.GetLongitude();
    y2=topRightPoint.GetLatitude();
    x3=bottomRightPoint.GetLongitude();
    y3=bottomRightPoint.GetLatitude();
    x4=bottomLeftPoint.GetLongitude();
    y4=bottomLeftPoint.GetLatitude();
    double c[]={
                    x1, y1, 1, 0, 0, 0, -x1*X1, -y1*X1,
                    0, 0, 0, x1, y1, 1, -x1*Y1, -y1*Y1,
                    x2, y2, 1, 0, 0, 0, -x2*X2, -y2*X2,
                    0, 0, 0, x2, y2, 1, -x2*Y2, -y2*Y2,
                    x3, y3, 1, 0, 0, 0, -x3*X3, -y3*X3,
                    0, 0, 0, x3, y3, 1, -x3*Y3, -y3*Y3,
                    x4, y4, 1, 0, 0, 0, -x4*X4, -y4*X4,
                    0, 0, 0, x4, y4, 1, -x4*Y4, -y4*Y4
               };
    double d[]={X1,Y1,X2,Y2,X3,Y3,X4,Y4};
    gauss(8,c,d);
    for (int i=0;i<8;i++)
        Xxkoef[i]=d[i];
}

void Map::GetCalibration(GeoCoordinates &topLeftPoint,
                         GeoCoordinates &topRightPoint,
                         GeoCoordinates &bottomRightPoint,
                         GeoCoordinates &bottomLeftPoint) const
{
    topLeftPoint.SetLatitude(topLeft.GetLatitude());
    topLeftPoint.SetLongitude(topLeft.GetLongitude());
    topRightPoint.SetLatitude(topRight.GetLatitude());
    topRightPoint.SetLongitude(topRight.GetLongitude());
    bottomRightPoint.SetLatitude(bottomRight.GetLatitude());
    bottomRightPoint.SetLongitude(bottomRight.GetLongitude());
    bottomLeftPoint.SetLatitude(bottomLeft.GetLatitude());
    bottomLeftPoint.SetLongitude(bottomLeft.GetLongitude());
}

double Map::CheckLine(const GeoCoordinates &a, const GeoCoordinates &b, const GeoCoordinates &c)
{
    return (b.GetLongitude()-a.GetLongitude())*(c.GetLatitude()-b.GetLatitude())-(a.GetLatitude()-b.GetLatitude())*(b.GetLongitude()-c.GetLongitude());
}

bool Map::CheckBorder(const GeoCoordinates &e)
{
    double ab=CheckLine(topLeft, e, topRight);
    double bc=CheckLine(topRight, e, bottomRight);
    double cd=CheckLine(bottomRight, e, bottomLeft);
    double da=CheckLine(bottomLeft, e, topLeft);
    return !(ab<0||bc<0||cd<0||da<0);
}
